#include "ISDU_SPACE.h"
#include "My_PARAM.h"
#include "Type_Define.h"
#include "math.h"
#include "PL.h"
#include <string.h>
#define StringFixedLength 5
//Index->Item数组下标映射表
//uint8_t   Variable_System_Command;
//uint8_t * System_Command=&Variable_System_Command;  //RAM , W
//
extern uint8_t System_Command;

//定义DataStrorageIndex 数据结构
typedef struct{
  uint16_t Index;
  uint8_t Subindex;
}Entry_of_IndexList_TYPE;

union  {
      struct {
          uint8_t DS_Command ;
          uint8_t State_Property ; 
          uint32_t Data_Storage_Szie ;
          uint32_t Parameter_Checksum ;
          Entry_of_IndexList_TYPE Entry[N_of_Index_List]; //可以在此初始化
          uint16_t TerminationMaker;

      }DataStorageIndexStruct;
      uint8_t Data[42]; //42字节限制了 N_of_Index_List<=10
} Data_Stroage_Index_Union={0x00,0x00,0x0000,0x0000}; 

uint8_t * Data_Storage_Index=Data_Stroage_Index_Union.Data;  // 不需要同步Falsh

 uint16_t Device_Access_Locks_Value=0x0000; 
uint16_t * Device_Acess_Locks=&Device_Access_Locks_Value; //EPROM存储，指针用于读取EPROM数据  
 
uint8_t * Profile_Characteristic;  //Flash ROM存储
//uint8_t * PDInputDescriptor ;      //Flash ROM
//uint8_t * PDOutputDescriptor ;     //Flash ROM
uint8_t   VendorName[] ="gongjunfeng"; // 
//uint8_t * VendorText ;//Flash ROM
uint8_t   ProductName[]="testDevice" ; // 
//uint8_t * ProductID ;//Flash ROM
//uint8_t * ProductText ;//Flash ROM
//uint8_t * Serial_Number ;//Flash ROM
//uint8_t * Hardware_Revision ;//Flash ROM
//uint8_t * Firmware_Revision ;//Flash ROM
//uint8_t * Application_Specific_Tag; //EPROM存储，指针用于读取EPROM数据
//uint8_t * Function_Tag;  //EPROM存储，指针用于读取EPROM数据
//uint8_t * Location_Tag;//EPROM存储，指针用于读取EPROM数据
//uint8_t * ErrorCount;  //Flash ROM
//uint8_t    Variable_Devcie_Status;
//uint8_t * Device_Status=&Variable_Devcie_Status; //RAM ,R

//uint8_t * Detailed_Device_Status; //RAM,R
//uint8_t * Process_Datainput; //Flash ROM,R
//uint8_t * Process_DataOutput;//Flash ROM,R
//uint8_t * Offset_Time; //Flash ROM,R


 /**********************

ISDU_Index_List_Typedef  Offset_TimeItem=
//Index      DataLen(Byte)            MemType      RWType    DataPointer              ISDU_SubIndexList         nextItem
{0x0030  ,   1              ,        EPROM   ,    RWAble , Offset_Time   ,             NULL,                     NULL};

ISDU_Index_List_Typedef Process_DataOutput=
//Index      DataLen(Byte)            MemType      RWType    DataPointer              ISDU_SubIndexList         nextItem
{0x0029  , PDOutLength    ,           RAM      ,  ReadOnly , Process_DataOutput,      NULL,                     Offset_TimeItem};


ISDU_Index_List_Typedef Process_DatainputItem=
//Index      DataLen(Byte)            MemType      RWType    DataPointer              ISDU_SubIndexList         nextItem
{0x0028 ,   PDInLength,               RAM,         ReadOnly ,Process_Datainput,       NULL ,                    Process_DataOutput};
]
ISDU_Index_List_Typedef Detailed_Device_StatusItem=
//Index      DataLen(Byte)            MemType      RWType    DataPointer              ISDU_SubIndexList         nextItem
{0x0025   ,   3*Error_n  ,             RAM   ,    ReadOnly , Detailed_Device_Status,  NULL,                Process_DatainputItem};

ISDU_Index_List_Typedef Device_StatusItem=
//Index      DataLen(Byte)            MemType      RWType    DataPointer              ISDU_SubIndexList         nextItem
{0x0024   ,     1                       RAM   ,    ReadOnly , Device_Status ,          NULL               ,     Detailed_Device_StatusItem};  

ISDU_Index_List_Typedef  ErrorCountItem=
//Index      DataLen(Byte)            MemType      RWType    DataPointer              ISDU_SubIndexList         nextItem
{0x0020,       2             ,        RAM  ,       ReadOnly , ErrorCount,                NULL,            Device_StatusItem};

ISDU_Index_List_Typedef  Location_TagItem=
//Index      DataLen(Byte)            MemType      RWType    DataPointer              ISDU_SubIndexList         nextItem
{0x001A   ,   Location_TagLen,       EPROM    ,    RWAble  ,  Location_Tag  ,           NULL      ,             ErrorCountItem };              


ISDU_Index_List_Typedef Function_TagItem=
//Index      DataLen(Byte)            MemType      RWType    DataPointer              ISDU_SubIndexList         nextItem
{0x0019 ,     FunctionTagLen,           EPROM ,     RWAble  ,  Function_Tag ,            NULL       ,       Location_TagItem    };

ISDU_Index_List_Typedef  Application_Specific_TagItem=
//Index      DataLen(Byte)            MemType      RWType    DataPointer              ISDU_SubIndexList         nextItem
{0x0018 , Application_Specific_TagLen, EPROM ,     RWAble , Application_Specific_Tag,      NULL,            &Function_TagItem    };


ISDU_Index_List_Typedef Firmware_RevisionItem=
//Index      DataLen(Byte)           MemType   RWType    DataPointer          ISDU_SubIndexList         nextItem
{0x0017  ,  Firmware_RevisionLen,    ROM ,     ReadOnly , Firmware_Revision ,  NULL,              &Application_Specific_TagItem}

ISDU_Index_List_Typedef Hardware_RevisionItem=
//Index      DataLen(Byte)           MemType   RWType    DataPointer          ISDU_SubIndexList         nextItem
{0x0016 ,  Hardware_RevisionItem,    ROM   ,   ReadOnly , Hardware_Revision,   NULL,               &Firmware_RevisionItem};

ISDU_Index_List_Typedef Serial_NumberItem=
//Index      DataLen(Byte)           MemType   RWType    DataPointer          ISDU_SubIndexList         nextItem
{0x0015 ,   Serial_NumberLen,         ROM,     ReadOnly , Serial_Number,       NULL,                    &Hardware_RevisionItem};

ISDU_Index_List_Typedef ProductTextItem=
//Index      DataLen(Byte)           MemType   RWType    DataPointer          ISDU_SubIndexList         nextItem
{0x0014,  ProductTextLen  ,           ROM,    ReadOnly, ProductText,         NULL,               , &Serial_NumberItem};

ISDU_Index_List_Typedef ProductIDItem=
//Index      DataLen(Byte)           MemType   RWType    DataPointer          ISDU_SubIndexList         nextItem
{0x0013,     ProductIDLen,           ROM    ,  ReadOnly, ProductID  ,         NULL,               &ProductTextItem };
**************************************/

/********************************************
ISDU_Index_List_Typedef VendorTextItem=
//Index      DataLen(Byte)           MemType   RWType    DataPointer          ISDU_SubIndexList         nextItem
{0x0011   , VendorTextLen  ,         ROM,      ReadOnly , VendorText ,       NULL          ,     &ProductNameItem   };

*************************************************/
 
/*****************************
ISDU_Index_List_Typedef PDOutputDescriptorItem=
//Index      DataLen(Byte)           MemType   RWType    DataPointer          ISDU_SubIndexList         nextItem
{0x000F   ,  PDOutputDescriptorLen,  ROM     , ReadOnly ,PDOutputDescriptor,  NULL             ,&VendorNameItem    };

ISDU_Index_List_Typedef PDInputDescriptorItem =
//Index      DataLen(Byte)           MemType   RWType    DataPointer          ISDU_SubIndexList         nextItem
{0x000E  ,  PDInputDescriptorLen,    ROM     ,ReadOnly,  PDInputDescriptor,     NULL  ,          &PDOutputDescriptorItem};      

ISDU_Index_List_Typedef ProfileCharacteristicItem=
//Index      DataLen(Byte)           MemType   RWType    DataPointer          ISDU_SubIndexList         nextItem
{0x000D ,ProfileCharacteristic_Len ,   ROM  , ReadOnly,Profile_Characteristic, NULL              ,&PDInputDescriptorItem };

ISDU_Index_List_Typedef DeviceAcessLockItem=
//Index      DataLen(Byte)       MemType   RWType    DataPointer          ISDU_SubIndexList         nextItem
{ 0x000c   ,  2              ,    EPROM,   RWAble  , Device_Acess_Locks ,          NULL     ,  &ProfileCharacteristicItem};
****************************/

/*******************ISDU Index 0x0003***************************************/
/*****************N_of_Index_List=(n*3+2)*8 见 Table B.11*****************************/
                                          // subindex    Byteoffset         字节长度       读写特性        上一项指针
ISDU_SubindexItem_Typedef  IndexList_of_DSIndex={0x05,   10        ,  N_of_Index_List,       R    ,         NULL      };
ISDU_SubindexItem_Typedef  PChecksum_of_DSIndex={0x04,    6        ,       4         ,       R    ,&IndexList_of_DSIndex};
ISDU_SubindexItem_Typedef  DS_Size_of_DSIndex  ={0x03,    2        ,       4         ,       R    ,&PChecksum_of_DSIndex};
ISDU_SubindexItem_Typedef  StateP_of_DSIndex   ={0x02,    1        ,       1         ,       R    ,&DS_Size_of_DSIndex } ;
ISDU_SubindexItem_Typedef  DS_Cmd_of_DSIndex   ={0x01,    0        ,       1         ,      RW   ,&StateP_of_DSIndex}; 

ISDU_Index_List_Typedef ProductNameItem=
//Index      DataLen(Byte)   RWType    DataPointer     ISDU_SubIndexList       flashAdrrss
{0x0012     ,    64       ,   R  ,     ProductName   ,      NULL         ,     FLASH_ADDR+N_of_Index_List+75    }; // 
//+75
ISDU_Index_List_Typedef  VendorNameItem=
//Index     DataLen(Byte)    RWType    DataPointer     ISDU_SubIndexList     flashAddresss
{0x0010 ,        64       ,    R ,     VendorName    ,        NULL        , FLASH_ADDR+N_of_Index_List+11 };
ISDU_Index_List_Typedef   DS_Index_Item= 
//Index      DataLen(Byte)   RWType    DataPointer     ISDU_SubIndexList    flashAddress
 {0x0003,N_of_Index_List+10,   RW,    Data_Stroage_Index_Union.Data, &DS_Cmd_of_DSIndex,    FLASH_ADDR+1   };

ISDU_Index_List_Typedef   System_CommandItem =
//Index     DataLen(Byte)    RWType    DataPointer     ISDU_SubIndexList    flashAddress
{0x0002 ,        1        ,    W ,    &System_Command  ,       NULL        ,  FLASH_ADDR+0     } ;


ISDU_Index_List_Typedef ISDU_List[ISDU_Item_NUM];
 

//恢复出厂设置，将RAM变量(可写的W)的内容写进Flash
void FallBack_to_Factory_ISDU_SPACE(void){
	 
    for(uint8_t i=0; i<ISDU_Item_NUM;i++){
       if((ISDU_List[i].ISDU_subindex_List==NULL)&&(ISDU_List[i].RWType&W)==W){
           PL_WriteFlash(ISDU_List[i].FlashAddress,ISDU_List[i].DataPointer,ISDU_List[i].DataLen);

       }else if(ISDU_List[i].ISDU_subindex_List!=NULL){
              ISDU_SubindexItem_Typedef * subISDU=ISDU_List[i].ISDU_subindex_List;
             while (subISDU!=NULL)
             {   
                //写Flash 数据
                PL_WriteFlash(ISDU_List[i].FlashAddress+subISDU->Offset,ISDU_List[i].DataPointer+subISDU->Offset,subISDU->DataLen);
                //更新subISDU指针
                subISDU=(ISDU_SubindexItem_Typedef * )subISDU->NextSubIndexItem;
             }
       }
    }
}

//初次上电时。需要把Flash中的数据(可写W)同步到RAM中
void Init_ISDU_SPACE(void){
	  //初始化参数结构,此处决定ISDU空间有哪些参数
    ISDU_List[0]=System_CommandItem;
	  ISDU_List[1]=DS_Index_Item;
	  ISDU_List[2]=VendorNameItem;
	  
	 
	
	  //参数与Flash同步
    for(uint8_t i=0;i<ISDU_Item_NUM;i++){
        //如果没有subIndex且可写
        if((ISDU_List[i].ISDU_subindex_List==NULL)&&(ISDU_List[i].RWType&W)==W){ 
            //从Flash中读出相应的数据
             PL_ReadFlash(ISDU_List[i].FlashAddress,ISDU_List[i].DataPointer,ISDU_List[i].DataLen);
        }else if(ISDU_List[i].ISDU_subindex_List!=NULL)
        {
             ISDU_SubindexItem_Typedef * subISDU=ISDU_List[i].ISDU_subindex_List;
             while (subISDU!=NULL)
             {   
                //从Flash中读出相应的数据
							  
                PL_ReadFlash(ISDU_List[i].FlashAddress+subISDU->Offset,ISDU_List[i].DataPointer+subISDU->Offset,subISDU->DataLen);
                //更新subISDU指针
                subISDU=(ISDU_SubindexItem_Typedef * )subISDU->NextSubIndexItem;
             }
              
        }
        
        
    }
}

//返回值是ErrorTYPE,写ISDU SPACE 同时写RAM 和ROM中的对应值，如果有SubIndex，限制不可整段写
uint16_t Write_ISDU_SPACE(uint16_t Index, uint8_t Subindex, uint8_t * Data, uint8_t DataLen){
    for(uint8_t i=0;i<ISDU_Item_NUM;i++){
        //查询Index
        if(Index==ISDU_List[i].Index){ //
            if(Subindex==0){ //写整段
                if((ISDU_List[i].RWType&W)!=W){
                    return 0x8023;//IDX_NOT_ACCESSIBLE
                }
                if(ISDU_List[i].ISDU_subindex_List!=NULL){ //如果有SubIndex，限制不可整段写
                    return 0x8023;//IDX_NOT_ACCESSIBLE
                }
                memcpy(ISDU_List[i].DataPointer,Data,DataLen); //写Ram
                PL_WriteFlash(ISDU_List[i].FlashAddress,Data,DataLen);//写FlashROM
                return 0x0000;
               
            }else{          //写单条ISDU
                //查找ISDU_SubindexItem 
                ISDU_SubindexItem_Typedef * subISDU=ISDU_List[i].ISDU_subindex_List;
                while(subISDU!=NULL){
                    //找到subIndex
                    if(subISDU->subIndex==Subindex){
                        if((subISDU->RWType&W)!=W){ //如果是不可泄的
                            return 0x8023; //IDX_NOT_ACCESSIBLE
                        }
                        //写RAM
                        memcpy(&ISDU_List[i].DataPointer[subISDU->Offset],Data,DataLen);
                        //写ROM
                        PL_WriteFlash(ISDU_List[i].FlashAddress+subISDU->Offset,Data,DataLen);
                        return 0x0000;
                        break;
                    }else{
                     //更新subISDU
                       subISDU=(ISDU_SubindexItem_Typedef*)subISDU->NextSubIndexItem;
                    }

                }//While结束
                //SubIndex查询不到
                return 0x8012; //SUBIDX_NOTAVAIL
    
 
            }
            
        }
    }
    //Index查询不到
    return 0x8011; //IDX_NOTAVAIL

}

//返回值为ErrorType
uint16_t ISDU_Read(uint16_t Index, uint8_t Subindex, uint8_t * ReadedData, uint8_t * ReadedDataLen){
    for(uint8_t i=0;i<ISDU_Item_NUM;i++){
        if(Index==ISDU_List[i].Index){ //找到Index
            if(Subindex==0){           //读取整段
                if((ISDU_List[i].RWType&R)!=R){
                    return 0x8023;//IDX_NOT_ACCESSIBLE
                }
                ReadedData=ISDU_List[i].DataPointer;
                *ReadedDataLen=ISDU_List[i].DataLen;
                return 0x0000;
            }else{      //读取subIndex数据
                //查找ISDU_SubindexItem 
                ISDU_SubindexItem_Typedef * subISDU=ISDU_List[i].ISDU_subindex_List;
               
                while(subISDU!=NULL){
                   //找到subIndex
                    if(subISDU->subIndex==Subindex){
                        if((subISDU->RWType&R)!=R){ //如果是不可泄的
                            return 0x8023; //IDX_NOT_ACCESSIBLE
                        }
                        ReadedData=&ISDU_List[i].DataPointer[subISDU->Offset];
                        *ReadedDataLen= subISDU->DataLen ;
                        return 0x0000;
                        break;
                    }else{
                     //更新subISDU
                       subISDU=(ISDU_SubindexItem_Typedef*)subISDU->NextSubIndexItem;
                    }

                }
                //SubIndex查询不到
                return 0x8012; //SUBIDX_NOTAVAIL
                
            }
        }
         
      
    }
    //Index查询不到
    return 0x8011; //IDX_NOTAVAIL
}

